package com.ywk.base.concurrency.thread.createWay;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * 线程创建方式3:实现Callable<T> 接口
 * @Author zbh
 * @Date 2024/1/2
 */
public class CallableTest implements Callable<Integer> {

    /**
     * 注：
     * 1.get()方法建议放在最后一行,防止线程阻塞(一旦调用了get()方法,不管是否计算完成都会阻塞;用 CompletableFuture 解决get()阻塞的问题)
     * 2.一个FutureTask,多个线程调用call()方法只会调用一次，如果需要调用call方法多次,则需要多个FutureTask
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //实现Callable接口 + FutureTask （可以拿到返回结果，可以处理异常）
        FutureTask<CallableTest> futureTask = new FutureTask(new CallableTest());
        new Thread(futureTask,"线程A").start();
//        new Thread(futureTask,"线程B").start();//多个线程调用call()方法只会调用一次
        //获取返回结果的两种方式：
        //1.get()方法获取，会阻塞等待整个线程执行完成（即：导致main线程阻塞）
//        System.out.println(futureTask.get());
        //如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞（轮询的方式会消耗无畏的CPU资源,而且也不见得能及时地得到计算的结果）
        while (true){
            if(futureTask.isDone()){
                System.out.println("使用轮询来解决,值为:"+futureTask.get());
                break;
            }else{
                System.out.println("非阻塞代码块**********");//看似不阻塞，只是一直在轮询，其结果看来主线程依旧是阻塞的
            }
        }
        System.out.println("当前线程："+Thread.currentThread().getName());
    }

    @Override
    public Integer call() throws Exception {
        System.out.println("当前线程："+Thread.currentThread().getName());
        //模拟业务处理时间
//        Thread.sleep(1000);
        return 66;
    }
}
